﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#pragma once

#include "GmPositioningElements.h"

#include "DbDataSchema.h"

#include "GbmpCalculatorBase.h"

#include "IElementShapeHandle.h"
#include "IElementShapeHandleBehavior.h"
#include "IElementMoveContext.h"
#include "IElementViewSpecificShapeComponent.h"
#include "IElementUiManipulatorComponent.h"
#include "IElementTransformationComponent.h"
#include "IElementCopyPasteComponent.h"
#include "IElementParametersCustomizer.h"
#include "IElementOffsetComponent.h"
#include "WeakPtr.h"
#include "IElement.h"
#include "IModelViewEventHandler.h"


namespace gcmp 
{
    class CommandParameters;

    // 轴网视图相关行为
    class SingleGridViewSpecificShapeComponent : public NdbObjectSchematic,
        public IElementViewSpecificShapeComponent,
        public IModelViewEventHandler
    {
        DBOBJECT_DATA_BEGIN_AND_QUICK_CAST_FROM(gcmp, SingleGridViewSpecificShapeComponent, gcmp::NdbObjectSchematic, 92780B71 - 080B - 4EEA - A62C - 121C30D68D1B, gmpositioningelements, IElementViewSpecificShapeComponent)
            DATA(OwnerPtr<IRenderPriorityOffsetProvider>, RenderPriorityOffsetProvider)
            DATA_TRANSIENT(IElement*, pOwnerElement)
            DATA(OwnerPtr<IGraphicsNodeVisibilityCustomizer>, GraphicsNodeVisibilityCustomizer)
        DBOBJECT_DATA_END
    public:

        virtual bool SetOwnerElement(IElement* pOwnerElement) override;
        virtual IElement* GetOwnerElement() override { return m_pOwnerElement; }
        virtual const IElement* GetOwnerElement() const override { return m_pOwnerElement; }

    public: //实现NdbObject接口
        virtual NdbObject* GetTopOwnerObject() const override
        {
            return nullptr;
        }

    public:
        virtual bool IsVisibleInModelView(const IModelView* pModelView) const override;
        virtual OwnerPtr<IGraphicsElementShape> CreateViewSpecificElementShape(const IModelView* pModelView) const override;
        virtual bool IsCuttableByModelViewRange(const IModelView* pModelView) const override { return false; }
        virtual void ReportDependentElements(std::vector<ElementId>& dependentElementIds) const override {};
        virtual bool NeedsRecreateViewSpecificElementShape(const IModelView* pModelView, const RecreateShapeInfo& shapeInfo) const override;

        virtual void SetRenderPriorityOffsetProvider(OwnerPtr<IRenderPriorityOffsetProvider> opProvider) override;
        virtual const IRenderPriorityOffsetProvider* GetRenderPriorityOffsetProvider() const override;
        virtual IRenderPriorityOffsetProvider* GetRenderPriorityOffsetProvider() override;

        virtual void SetGraphicsNodeVisibilityCustomizer(OwnerPtr<IGraphicsNodeVisibilityCustomizer> opCustomizer) override;
        virtual const IGraphicsNodeVisibilityCustomizer* GetGraphicsNodeVisibilityCustomizer() const override;
        virtual IGraphicsNodeVisibilityCustomizer* GetGraphicsNodeVisibilityCustomizer() override;
        // 继承自IModelViewEventHandler
    public:
        virtual void On(IModelViewEventArgs* pArgs) override;
    };

    // 夹点位置更新计算器
    class SingleGridGripPointPositionCalculator : public GbmpCalculatorBase
    {
        DECLARE_CALCULATOR(SingleGridGripPointPositionCalculator, IElementShapeHandle)
    public:
        SingleGridGripPointPositionCalculator(IDocument* pDoc, const RegenDataId& outputDataId) : GbmpCalculatorBase(pDoc, outputDataId) {}
        virtual void ReportInputDataIds(std::vector<RegenDataId> & dataIds) const override;
        virtual void Execute() override;
    };

    // 轴网控制点类型
    enum class GridControlPointType : int8_t
    {
        None = 0,
        HorizontalStart = 1, // 水平向起点
        HorizontalEnd = 2,  // 水平向终点
        VerticalStart = 3,  // 竖直向起点
        VerticalEnd = 4,    // 竖直向终点
        // ... 
    };

    // 夹点更新行为
    class GM_POSITIONING_ELEMENTS_EXPORT SingleGridGripPointBehavior :public NdbObjectSchematic, public IElementShapeHandleBehavior
    {
        DBOBJECT_DATA_BEGIN_AND_QUICK_CAST_FROM(gcmp, SingleGridGripPointBehavior, gcmp::NdbObjectSchematic, BDC514F2 - AD04 - 46CD - BD69 - 81392345A081, gmpositioningelements, gcmp::IElementShapeHandleBehavior)
           DATA(IDocument*, Document)
           DATA(ElementId, ModelViewId)    //表示这个夹点在哪个视图上显示的(切换视图夹点会刷新)
           DATA(GridControlPointType, PositionType)
           DATA(ElementId, ElementShapeHandleId)
        DBOBJECT_DATA_END

    public:
        static OwnerPtr<IElementShapeHandleBehavior> Create(IDocument* pDoc, const ElementId& modelViewId);
        virtual ~SingleGridGripPointBehavior() {}

    public:
        virtual IDocument* GetDocument() const override { return GetDocument__(); }
        void SetDocument(const IDocument* pDoc) { SetDocument__(pDoc); }

        virtual ElementId GetModelViewId() const override { return GetModelViewId__(); }
        void SetModelViewId(const ElementId &modelViewId) { SetModelViewId__(modelViewId); }

        virtual ElementId GetElementShapeHandleId() const override { return GetElementShapeHandleId__(); }
        virtual void SetElementShapeHandleId(const ElementId& id) override { return SetElementShapeHandleId__(id); }

        virtual void GetCalculators(ICalculatorCollection* calculators) const override;
        virtual bool Translate(const IElementMoveContext & moveContext) override; 

        virtual OwnerPtr<IGraphicsElementShape> CreateGrahicsElementShapeInModelView(const IModelView* pModelView) const override;
        virtual void ReportParents(IElementParentReporter& reporter) const override;

        virtual void UpdatePosition() override;
        virtual void UpdatePositionIndexInMasterElement() override {};

        virtual void GetNearestPoint(Vector3d& nearPoint) const override;

        virtual bool FinishEditing() override { return false; }
        virtual bool GetHandleCommandString(const IObject* commandEnvironment, std::wstring& commandStr, CommandParameters& cmdParams) const override;

    public: //实现NdbObject接口
        virtual NdbObject* GetTopOwnerObject() const override
        {
            return nullptr;
        }

    private:
        SingleGridGripPointBehavior(IDocument* pDoc, const ElementId& modelViewId);
        IElementShapeHandle* GetElementShapeHandle() const;
    };
    

    // 辅助对象创建行为
    class SingleGridUiManipulatorComponent : public NdbObjectSchematic, public IElementUiManipulatorComponent
    {
        DBOBJECT_DATA_BEGIN_AND_QUICK_CAST_FROM(gcmp, SingleGridUiManipulatorComponent, gcmp::NdbObjectSchematic, F756EA4B - 9147 - 48AF - A005 - D3D00E736B46, gmpositioningelements, IElementUiManipulatorComponent)
        DBOBJECT_DATA_END
    public:
        virtual bool SetOwnerElement(IElement* pOwnerElement) override { m_pOwnerElement = pOwnerElement; return true; }
        virtual IElement* GetOwnerElement() override { return m_pOwnerElement; }
        virtual const IElement* GetOwnerElement() const override { return m_pOwnerElement; }

    public: //实现NdbObject接口
        virtual NdbObject* GetTopOwnerObject() const override
        {
            return nullptr;
        }
    private:
        ElementId CreateGripPoint(GridControlPointType type, const gcmp::ElementId& modelviewId) const;
    private:
        IElement* m_pOwnerElement;
    };
    
    // 移动、旋转行为
    class SingleGridTransformationComponent :public NdbObjectSchematic, public IElementTransformationComponent
    {
        DBOBJECT_DATA_BEGIN(gcmp, SingleGridTransformationComponent, gcmp::NdbObjectSchematic, DF8602D2 - 7B21 - 494A - A014 - FE0F71AF97C1, gmpositioningelements)
        DBOBJECT_DATA_END
    public:
        virtual bool SetOwnerElement(IElement* pOwnerElement) override { m_pOwnerElement = pOwnerElement; return true; }
        virtual IElement* GetOwnerElement() override { return m_pOwnerElement.Get(); }
        virtual const IElement* GetOwnerElement() const override { return m_pOwnerElement.Get(); }

        virtual bool CanBeMoved(std::wstring* explanation = nullptr) const override;
        virtual bool Translate(const IElementMoveContext& moveContext) override;

        virtual bool CanBeRotated(std::wstring* explanation = nullptr) const override;
        virtual bool Rotate(const Vector3d& pointOnVec, const Vector3d& rotateDir, double rotateAngle) override;

        virtual bool CanBeScaled(std::wstring* explanation = nullptr) const override { return false; }
        virtual bool Scale(const Vector3d& basePt, float scaleFactor) override { return false; }

        virtual bool Transform(const Matrix4d& matrix) override;

    public: //实现NdbObject接口
        virtual NdbObject* GetTopOwnerObject() const override
        {
            return nullptr;
        }

    private:
        WeakPtr<IElement> m_pOwnerElement;
    };

    // 拷贝行为
    class SingleGridCopyPasteComponent : public NdbObjectSchematic, public IElementCopyPasteComponent
    {
        DBOBJECT_DATA_BEGIN_AND_QUICK_CAST_FROM(gcmp,SingleGridCopyPasteComponent, gcmp::NdbObjectSchematic, 14B77F66 - 51C0 - 4B85 - 9498 - 14059442C271, gmpositioningelements, IElementCopyPasteComponent)
        DBOBJECT_DATA_END
    public:
        explicit SingleGridCopyPasteComponent(IElement* pOwnerElement)
            : m_pOwnerElement(pOwnerElement)
        {}
    public:
        virtual OwnerPtr<IPasteHelper> GetPasteHelper() const override { return nullptr; }

        virtual void UpdateAfterCopy(const ICopyContext& copyContext) override;

        virtual void UpdateForWeakParentCopied(const IDocument* pDocFrom, const IElement* pSource, const IElement* pCopy) const override;

        virtual bool ShouldBeCopiedTogether(const ICopyContext & copyContext) const override;

        virtual bool IsStrongParentsNeedCopied() const override;

        virtual bool CanBeCopied(std::wstring* pErrorMessage) const override;

    public:
        virtual bool SetOwnerElement(IElement* pOwnerElement) override { m_pOwnerElement = pOwnerElement; return true; }
        virtual IElement* GetOwnerElement() override { return m_pOwnerElement; }
        virtual const IElement* GetOwnerElement() const override { return m_pOwnerElement; }

        // 辅助方法
        IDocument* GetDocument() const;
        ElementId GetOwnerElementId() const;

    public: //实现NdbObject接口
        virtual NdbObject* GetTopOwnerObject() const override
        {
            return nullptr;
        }

    private:
        IElement* m_pOwnerElement;
    };

    // 参数行为
    class SingleGridParametersCustomizer : public NdbObjectSchematic, public IElementParametersCustomizer
    {
        DBOBJECT_DATA_BEGIN_AND_QUICK_CAST_FROM(gcmp, SingleGridParametersCustomizer, gcmp::NdbObjectSchematic, 4C718389-2874-42A0-943C-892294DB289B, gmpositioningelements, IElementParametersCustomizer)
        DBOBJECT_DATA_END
    public:
        SingleGridParametersCustomizer(const IElement* pElement);

        virtual OwnerPtr<IParameter> GetNativeParameter(int paramDefId) const override;
        virtual bool SetNativeParameter(const IParameter *param, std::wstring* errorMsg) override;
        virtual void ReportParameterDefinitions(std::vector<int>* pParamDefIds) const override;
        virtual bool IsParameterModifiable(int parameterId) const override { return true; }
        virtual bool IsPresetParameter(const UniIdentity& parameterDefinitionUid) const override;
        virtual void FilterParameterValues(const UniIdentity& paramDefUid, 
            std::vector<OwnerPtr<IParameterValueStorage>>& values) const override {}
        
    public:
        virtual bool SetOwnerElement(IElement* pOwnerElement) override { m_pOwnerElement = pOwnerElement; return true; }
        virtual IElement* GetOwnerElement() override { return m_pOwnerElement.Get(); }
        virtual const IElement* GetOwnerElement() const override { return m_pOwnerElement.Get(); }

    public: //实现NdbObject接口
        virtual NdbObject* GetTopOwnerObject() const override
        {
            return nullptr;
        }

    protected:
        IDocument* GetDocument() const;
        ElementId GetOwnerElementId() const;
    private:
        WeakPtr<IElement> m_pOwnerElement;

    };
    // 偏移行为
    class SingleGridOffsetComponent : public NdbObjectSchematic, public IElementOffsetComponent
    {
        DBOBJECT_DATA_BEGIN_AND_QUICK_CAST_FROM(gcmp, SingleGridOffsetComponent, gcmp::NdbObjectSchematic, B967FE87 - 684D - 4011 - B051 - CA348D512C3F,
            gmpositioningelements, gcmp::IElementOffsetComponent)
            DBOBJECT_DATA_END
    public:
        virtual ~SingleGridOffsetComponent(){}
        explicit SingleGridOffsetComponent(IElement* pOwnerElement)
            : m_pOwnerElement(pOwnerElement)
        {}

    public:
        virtual bool SetOwnerElement(IElement* pOwnerElement) override { m_pOwnerElement = pOwnerElement; return true; }
        virtual IElement* GetOwnerElement() override { return m_pOwnerElement.Get(); }
        virtual const IElement* GetOwnerElement() const override { return m_pOwnerElement.Get(); }

    public: //实现NdbObject接口
        virtual NdbObject* GetTopOwnerObject() const override
        {
            return nullptr;
        }

    public:
        virtual bool CanBeOffset(std::wstring* explanation = nullptr) const override;
        virtual bool CanBeOffsetConnected() const override { return false; }
        virtual ElementIdArray GetElementsCanBeOffsetConnected() const override { return ElementIdArray(); }
        virtual std::vector<OwnerPtr<ICurve3d>> GetOffsetBaseCurves(const IPlane* pBasePlane) const override;
        virtual bool SetOffsetBaseCurves(const IPlane* pBasePlane, const std::vector<const ICurve3d *>& vCurves) override;
    private:
        WeakPtr<IElement> m_pOwnerElement;
    };

}// namespace gcmp
